#include "ast.h"
#include <sstream>

// Expression implementations
std::string Expression::toString() const {
    return value;
}

std::string BinaryExpression::toString() const {
    std::ostringstream oss;
    oss << "(" << left->toString() << " " << static_cast<int>(operatorType) << " " << right->toString() << ")";
    return oss.str();
}

std::string UnaryExpression::toString() const {
    std::ostringstream oss;
    oss << static_cast<int>(operatorType) << operand->toString();
    return oss.str();
}

std::string FunctionCall::toString() const {
    std::ostringstream oss;
    oss << functionName << "(";
    for (size_t i = 0; i < arguments.size(); ++i) {
        if (i > 0) oss << ", ";
        oss << arguments[i]->toString();
    }
    oss << ")";
    return oss.str();
}

// Statement implementations
std::string ExpressionStatement::toString() const {
    return expression ? expression->toString() + ";" : ";";
}

std::string ReturnStatement::toString() const {
    if (expression) {
        return "return " + expression->toString() + ";";
    }
    return "return;";
}

std::string IfStatement::toString() const {
    std::ostringstream oss;
    oss << "if (" << condition->toString() << ") " << thenBranch->toString();
    if (elseBranch) {
        oss << " else " << elseBranch->toString();
    }
    return oss.str();
}

std::string WhileStatement::toString() const {
    return "while (" + condition->toString() + ") " + body->toString();
}

std::string BlockStatement::toString() const {
    std::ostringstream oss;
    oss << "{\n";
    for (const auto& stmt : statements) {
        oss << "  " << stmt->toString() << "\n";
    }
    oss << "}";
    return oss.str();
}

// Declaration implementations
std::string VariableDeclaration::toString() const {
    std::ostringstream oss;
    oss << static_cast<int>(type) << " " << name;
    if (initializer) {
        oss << " = " << initializer->toString();
    }
    oss << ";";
    return oss.str();
}

std::string FunctionDeclaration::toString() const {
    std::ostringstream oss;
    oss << static_cast<int>(returnType) << " " << name << "(";
    for (size_t i = 0; i < parameters.size(); ++i) {
        if (i > 0) oss << ", ";
        oss << static_cast<int>(parameters[i].first) << " " << parameters[i].second;
    }
    oss << ") " << body->toString();
    return oss.str();
}

std::string Program::toString() const {
    std::ostringstream oss;
    for (const auto& decl : declarations) {
        oss << decl->toString() << "\n";
    }
    return oss.str();
}
